﻿using CI.Interfaces;
using CI.Misc;
using CI.Organism;
using NUnit.Framework;

namespace Mesopotamia.UnitTests.Organism
{
    [TestFixture]
    public class OrganismCollectionTests
    {
        private IOrganismCollection _organisms;
        readonly IHostingEnvironment _hostingEnvironment = new CI.Mesopotamia.MSRBHost(new MockHostingEnvironmentPhysical(), new CI.Mesopotamia.ScenarioLocalXML());
        private const int ORGANISMS_COUNT = 100;          // how many childOrganism added to the list
        private const int CIET_HIGHT = 100;               // high ciet org

        /// <summary>
        /// setup
        /// </summary>
        [SetUp]
        public void Setup()
        {
            // create a new list
            _organisms = new CI.Organism.OrganismCollection();

            // add organisms
            for (int i = 0; i < ORGANISMS_COUNT; i += 2)
            {
                _organisms.AliveAdd(new CI.Organism.Organism(_hostingEnvironment));
                _organisms.DeadAdd(new CI.Organism.Organism(_hostingEnvironment));
            }

            // set them to all clean in alive
            foreach (IOrganism organism in _organisms.Alive)
            {
                organism.Location = _hostingEnvironment.HostingEnvironmentPhysical.SetLocation(organism, new CI.Organism.Location());
                organism.LocationDirty = false;
            }

            // set them to all clean in alive
            foreach (IOrganism organism in _organisms.Dead)
            {
                organism.Location = _hostingEnvironment.HostingEnvironmentPhysical.SetLocation(organism, new CI.Organism.Location());
                organism.LocationDirty = false;
            }

            ((CI.Mesopotamia.MSRBHost)_hostingEnvironment).SystemHeartBeat++;
        }

        /// <summary>
        /// This test calls the check dirty locations rebuid with none changed so the list comes out empty
        /// </summary>
        [Test]
        public void DirtyLocationsRebuildNoneEmpty()
        {
            // rebuild
            _organisms.DirtyLocationsRebuild();

            // check
            Assert.AreEqual(0, _organisms.DirtyLocations.Count, "Dirty List should be empty");
        }

        /// <summary>
        /// Alive, This test calls the check dirty locations rebuid with one change
        /// </summary>
        [Test]
        public void DirtyLocationsRebuildAlive1ChangeEqual()
        {
            // set it to be dirty
            _organisms.Alive[ORGANISMS_COUNT / 2 - 1].LocationDirty = true;
            _organisms.Alive[ORGANISMS_COUNT / 2 - 1].CIET = CIET_HIGHT;

            // rebuild
            _organisms.DirtyLocationsRebuild();

            // check
            Assert.AreEqual(1, _organisms.DirtyLocations.Count, "Dirty List should have objects");
        }

        /// <summary>
        /// Alive, This test calls the check dirty locations rebuid with all changed
        /// </summary>
        [Test]
        public void DirtyLocationsRebuildAlive50ChangeEqual()
        {
            // set them to all clean in alive and give them a ciet
            foreach (IOrganism organism in _organisms.Alive)
            {
                organism.CIET = CIET_HIGHT;
                organism.LocationDirty = true;
            }

            // rebuild
            _organisms.DirtyLocationsRebuild();

            // check
            Assert.AreEqual(ORGANISMS_COUNT / 2, _organisms.DirtyLocations.Count, "Dirty List should have objects");
        }

        /// <summary>
        /// Dead, This test calls the check dirty locations rebuid with one change
        /// </summary>
        [Test]
        public void DirtyLocationsRebuildDead1ChangeEqual()
        {
            // set it to be dirty
            _organisms.Dead[ORGANISMS_COUNT / 2 - 1].LocationDirty = true;
            _organisms.Dead[ORGANISMS_COUNT / 2 - 1].CIET = CIET_HIGHT;

            // rebuild
            _organisms.DirtyLocationsRebuild();

            // check
            Assert.AreEqual(1, _organisms.DirtyLocations.Count, "Dirty List should have objects");
        }

        /// <summary>
        /// Dead, This test calls the check dirty locations rebuid with all changed
        /// </summary>
        [Test]
        public void DirtyLocationsRebuildDead50ChangeEqual()
        {
            // set them to all clean in alive
            foreach (IOrganism organism in _organisms.Dead)
            {
                organism.LocationDirty = true;
                organism.CIET = CIET_HIGHT;
            }

            // rebuild
            _organisms.DirtyLocationsRebuild();

            // check
            Assert.AreEqual(ORGANISMS_COUNT / 2, _organisms.DirtyLocations.Count, "Dirty List should have objects");
        }

        /// <summary>
        /// This test calls the check dirty locations rebuid with all changed so the list comes out full 
        /// </summary>
        [Test]
        public void DirtyLocationsRebuildClearFullListEqual()
        {
            // set them to all dirty in alive
            foreach (IOrganism organism in _organisms.Alive)
            {
                organism.LocationDirty = true;
                organism.CIET = CIET_HIGHT;
            }

            // set them to all dirty in dead
            foreach (IOrganism organism in _organisms.Dead)
            {
                organism.LocationDirty = true;
                organism.CIET = CIET_HIGHT;
            }

            // rebuild this should create the dirty list and set the all to be clear
            _organisms.DirtyLocationsRebuild();

            // check that list is full
            Assert.AreEqual(ORGANISMS_COUNT, _organisms.DirtyLocations.Count, "Dirty List should be full");
        }

        /// <summary>
        /// Make sure they are set to false after a rebuild of the list
        /// </summary>
        [Test]
        public void DirtyLocationsRebuildClearDirtyFalse()
        {
            // set them to all dirty in alive
            foreach (IOrganism organism in _organisms.Alive)
            {
                organism.LocationDirty = true;
                organism.CIET = CIET_HIGHT;
            }

            // set them to all dirty in dead
            foreach (IOrganism organism in _organisms.Dead)
            {
                organism.LocationDirty = true;
                organism.CIET = CIET_HIGHT;
            }

            // rebuild this should create the dirty list and set the all to be clear
            _organisms.DirtyLocationsRebuild();

            // check and make sure the are all cleared
            foreach (IOrganism organism in _organisms.Alive)
            {
                Assert.IsFalse(organism.LocationDirty, "Dirty Location should be false after list rebuilt");
            }
            foreach (IOrganism organism in _organisms.Dead)
            {
                Assert.IsFalse(organism.LocationDirty, "Dirty Location should be false after list rebuilt");
            }
        }

    }
}